package com.yunke.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yunke.common.result.YunkeResult;
import com.yunke.dto.chat.YunkeCheckUserInfoDto;
import com.yunke.dto.chat.YunkeSendMessageDto;
import com.yunke.service.YunkeChatService;
import com.yunke.vo.chat.YunkeChatVo;
import com.yunke.vo.chat.YunkeMessageVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import jakarta.validation.Valid;
import java.util.List;
import java.util.Map;

/**
 * 聊天通讯Controller
 * 
 * @author yunke
 * @since 1.0.0
 */
@Slf4j
@RestController
@RequestMapping("/api/chat")
@Tag(name = "聊天通讯管理", description = "聊天通讯相关接口")
public class YunkeChatController {

    @Autowired
    private YunkeChatService chatService;

    /**
     * 获取聊天列表
     */
    @GetMapping("/list")
    @Operation(summary = "获取聊天列表", description = "获取当前用户的聊天会话列表")
    public YunkeResult<Page<YunkeChatVo>> getChatList(
            @Parameter(description = "当前页码") @RequestParam(defaultValue = "1") Long current,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Long size) {
        
        log.info("获取聊天列表，页码：{}，大小：{}", current, size);
        
        try {
            Page<YunkeChatVo> result = chatService.getChatList(current, size);
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("获取聊天列表失败", e);
            return YunkeResult.error("获取聊天列表失败：" + e.getMessage());
        }
    }

    /**
     * 获取聊天记录
     */
    @GetMapping("/history/{chatId}")
    @Operation(summary = "获取聊天记录", description = "获取指定聊天室的消息记录")
    public YunkeResult<Page<YunkeMessageVo>> getChatHistory(
            @Parameter(description = "聊天室ID") @PathVariable String chatId,
            @Parameter(description = "当前页码") @RequestParam(defaultValue = "1") Long current,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "20") Long size) {
        
        log.info("获取聊天记录，聊天室ID：{}，页码：{}，大小：{}", chatId, current, size);
        
        try {
            Page<YunkeMessageVo> result = chatService.getChatHistory(chatId, current, size);
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("获取聊天记录失败，聊天室ID：{}", chatId, e);
            return YunkeResult.error("获取聊天记录失败：" + e.getMessage());
        }
    }

    /**
     * 发送消息
     */
    @PostMapping("/send")
    @Operation(summary = "发送消息", description = "发送文字、位置等消息")
    public YunkeResult<YunkeMessageVo> sendMessage(@Valid @RequestBody YunkeSendMessageDto sendMessageDto) {
        
        log.info("发送消息，接收者：{}，类型：{}", sendMessageDto.getReceiverId(), sendMessageDto.getMessageType());
        
        try {
            YunkeMessageVo result = chatService.sendMessage(sendMessageDto);
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("发送消息失败", e);
            return YunkeResult.error("发送消息失败：" + e.getMessage());
        }
    }

    /**
     * 发送图片消息
     */
    @PostMapping("/sendImage")
    @Operation(summary = "发送图片消息", description = "发送图片类型的消息")
    public YunkeResult<YunkeMessageVo> sendImageMessage(
            @Parameter(description = "接收者用户ID") @RequestParam Long receiverId,
            @Parameter(description = "图片文件") @RequestParam MultipartFile imageFile,
            @Parameter(description = "回复的消息ID") @RequestParam(required = false) String replyMessageId) {
        
        log.info("发送图片消息，接收者：{}", receiverId);
        
        try {
            YunkeMessageVo result = chatService.sendImageMessage(receiverId, imageFile, replyMessageId);
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("发送图片消息失败", e);
            return YunkeResult.error("发送图片消息失败：" + e.getMessage());
        }
    }

    /**
     * 发送语音消息
     */
    @PostMapping("/sendVoice")
    @Operation(summary = "发送语音消息", description = "发送语音类型的消息")
    public YunkeResult<YunkeMessageVo> sendVoiceMessage(
            @Parameter(description = "接收者用户ID") @RequestParam Long receiverId,
            @Parameter(description = "语音文件") @RequestParam MultipartFile voiceFile,
            @Parameter(description = "语音时长（秒）") @RequestParam Integer duration,
            @Parameter(description = "回复的消息ID") @RequestParam(required = false) String replyMessageId) {
        
        log.info("发送语音消息，接收者：{}，时长：{}秒", receiverId, duration);
        
        try {
            YunkeMessageVo result = chatService.sendVoiceMessage(receiverId, voiceFile, duration, replyMessageId);
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("发送语音消息失败", e);
            return YunkeResult.error("发送语音消息失败：" + e.getMessage());
        }
    }

    /**
     * 发送位置消息
     */
    @PostMapping("/sendLocation")
    @Operation(summary = "发送位置消息", description = "发送位置类型的消息")
    public YunkeResult<YunkeMessageVo> sendLocationMessage(
            @Parameter(description = "接收者用户ID") @RequestParam Long receiverId,
            @Parameter(description = "经度") @RequestParam Double longitude,
            @Parameter(description = "纬度") @RequestParam Double latitude,
            @Parameter(description = "地址") @RequestParam String address,
            @Parameter(description = "回复的消息ID") @RequestParam(required = false) String replyMessageId) {
        
        log.info("发送位置消息，接收者：{}，位置：{}", receiverId, address);
        
        try {
            YunkeMessageVo result = chatService.sendLocationMessage(receiverId, longitude, latitude, address, replyMessageId);
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("发送位置消息失败", e);
            return YunkeResult.error("发送位置消息失败：" + e.getMessage());
        }
    }

    /**
     * 标记消息已读
     */
    @PostMapping("/markRead")
    @Operation(summary = "标记消息已读", description = "标记指定消息为已读状态")
    public YunkeResult<Boolean> markMessagesAsRead(
            @Parameter(description = "聊天室ID") @RequestParam String chatId,
            @Parameter(description = "消息ID列表") @RequestBody List<String> messageIds) {
        
        log.info("标记消息已读，聊天室ID：{}，消息数量：{}", chatId, messageIds.size());
        
        try {
            boolean result = chatService.markMessagesAsRead(chatId, messageIds);
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("标记消息已读失败", e);
            return YunkeResult.error("标记消息已读失败：" + e.getMessage());
        }
    }

    /**
     * 删除聊天记录
     */
    @DeleteMapping("/delete")
    @Operation(summary = "删除聊天记录", description = "删除单条消息或清空聊天记录")
    public YunkeResult<Boolean> deleteChatRecord(
            @Parameter(description = "聊天室ID") @RequestParam String chatId,
            @Parameter(description = "删除类型：1-删除单条消息 2-清空聊天记录") @RequestParam Integer deleteType,
            @Parameter(description = "消息ID列表") @RequestBody(required = false) List<String> messageIds) {
        
        log.info("删除聊天记录，聊天室ID：{}，删除类型：{}", chatId, deleteType);
        
        try {
            boolean result = chatService.deleteChatRecord(chatId, deleteType, messageIds);
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("删除聊天记录失败", e);
            return YunkeResult.error("删除聊天记录失败：" + e.getMessage());
        }
    }

    /**
     * 设置聊天置顶
     */
    @PostMapping("/setTop")
    @Operation(summary = "设置聊天置顶", description = "设置或取消聊天会话置顶")
    public YunkeResult<Boolean> setChatTop(
            @Parameter(description = "聊天室ID") @RequestParam String chatId,
            @Parameter(description = "是否置顶") @RequestParam Boolean isTop) {
        
        log.info("设置聊天置顶，聊天室ID：{}，置顶：{}", chatId, isTop);
        
        try {
            boolean result = chatService.setChatTop(chatId, isTop);
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("设置聊天置顶失败", e);
            return YunkeResult.error("设置聊天置顶失败：" + e.getMessage());
        }
    }

    /**
     * 消息免打扰
     */
    @PostMapping("/setMute")
    @Operation(summary = "消息免打扰", description = "设置或取消聊天消息免打扰")
    public YunkeResult<Boolean> setChatMute(
            @Parameter(description = "聊天室ID") @RequestParam String chatId,
            @Parameter(description = "是否免打扰") @RequestParam Boolean isMute) {
        
        log.info("设置消息免打扰，聊天室ID：{}，免打扰：{}", chatId, isMute);
        
        try {
            boolean result = chatService.setChatMute(chatId, isMute);
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("设置消息免打扰失败", e);
            return YunkeResult.error("设置消息免打扰失败：" + e.getMessage());
        }
    }

    /**
     * 查看用户信息申请
     */
    @PostMapping("/checkUserInfo")
    @Operation(summary = "查看用户信息申请", description = "申请查看用户联系方式等信息")
    public YunkeResult<Map<String, Object>> checkUserInfoApply(@Valid @RequestBody YunkeCheckUserInfoDto checkUserInfoDto) {
        
        log.info("查看用户信息申请，目标用户：{}，查看类型：{}", checkUserInfoDto.getTargetUserId(), checkUserInfoDto.getCheckType());
        
        try {
            Map<String, Object> result = chatService.checkUserInfoApply(checkUserInfoDto);
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("查看用户信息申请失败", e);
            return YunkeResult.error("查看用户信息申请失败：" + e.getMessage());
        }
    }

    /**
     * 获取未读消息数量
     */
    @GetMapping("/unreadCount")
    @Operation(summary = "获取未读消息数量", description = "获取当前用户的未读消息统计")
    public YunkeResult<Map<String, Object>> getUnreadCount() {
        
        log.info("获取未读消息数量");
        
        try {
            Map<String, Object> result = chatService.getUnreadCount();
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("获取未读消息数量失败", e);
            return YunkeResult.error("获取未读消息数量失败：" + e.getMessage());
        }
    }

    /**
     * 搜索聊天记录
     */
    @GetMapping("/search")
    @Operation(summary = "搜索聊天记录", description = "在指定聊天室中搜索消息")
    public YunkeResult<Page<YunkeMessageVo>> searchChatHistory(
            @Parameter(description = "聊天室ID") @RequestParam String chatId,
            @Parameter(description = "搜索关键词") @RequestParam String keyword,
            @Parameter(description = "消息类型筛选") @RequestParam(required = false) Integer messageType,
            @Parameter(description = "当前页码") @RequestParam(defaultValue = "1") Long current,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Long size) {
        
        log.info("搜索聊天记录，聊天室ID：{}，关键词：{}", chatId, keyword);
        
        try {
            Page<YunkeMessageVo> result = chatService.searchChatHistory(chatId, keyword, messageType, current, size);
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("搜索聊天记录失败", e);
            return YunkeResult.error("搜索聊天记录失败：" + e.getMessage());
        }
    }

    /**
     * 撤回消息
     */
    @PostMapping("/recall/{messageId}")
    @Operation(summary = "撤回消息", description = "撤回已发送的消息")
    public YunkeResult<Boolean> recallMessage(
            @Parameter(description = "消息ID") @PathVariable String messageId,
            @Parameter(description = "撤回原因") @RequestParam(required = false) String reason) {
        
        log.info("撤回消息，消息ID：{}", messageId);
        
        try {
            boolean result = chatService.recallMessage(messageId, reason);
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("撤回消息失败", e);
            return YunkeResult.error("撤回消息失败：" + e.getMessage());
        }
    }

    /**
     * WebSocket连接（用于前端调用，实际处理在WebSocket处理器中）
     */
    @PostMapping("/connect")
    @Operation(summary = "建立WebSocket连接", description = "建立实时通讯连接")
    public YunkeResult<Boolean> connectWebSocket(
            @Parameter(description = "会话ID") @RequestParam String sessionId) {
        
        log.info("建立WebSocket连接，会话ID：{}", sessionId);
        
        try {
            // 这里主要用于前端获取连接状态，实际连接在WebSocket处理器中
            return YunkeResult.success(true);
        } catch (Exception e) {
            log.error("建立WebSocket连接失败", e);
            return YunkeResult.error("建立WebSocket连接失败：" + e.getMessage());
        }
    }

    /**
     * 发起语音通话
     */
    @PostMapping("/call/{receiverId}")
    @Operation(summary = "发起语音通话", description = "发起语音或视频通话")
    public YunkeResult<Map<String, Object>> initiateCall(
            @Parameter(description = "接收者用户ID") @PathVariable Long receiverId,
            @Parameter(description = "通话类型：1-语音通话 2-视频通话") @RequestParam Integer callType) {
        
        log.info("发起语音通话，接收者：{}，类型：{}", receiverId, callType);
        
        try {
            Map<String, Object> result = chatService.initiateCall(receiverId, callType);
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("发起语音通话失败", e);
            return YunkeResult.error("发起语音通话失败：" + e.getMessage());
        }
    }

    /**
     * 响应语音通话
     */
    @PostMapping("/call/respond/{callId}")
    @Operation(summary = "响应语音通话", description = "接听、拒绝或挂断通话")
    public YunkeResult<Boolean> respondCall(
            @Parameter(description = "通话ID") @PathVariable String callId,
            @Parameter(description = "响应动作：1-接听 2-拒绝 3-挂断") @RequestParam Integer action) {
        
        log.info("响应语音通话，通话ID：{}，动作：{}", callId, action);
        
        try {
            boolean result = chatService.respondCall(callId, action);
            return YunkeResult.success(result);
        } catch (Exception e) {
            log.error("响应语音通话失败", e);
            return YunkeResult.error("响应语音通话失败：" + e.getMessage());
        }
    }
} 